package pl.softech.demo2d.physics.fluid;

import pl.softech.demo2d.physics.fluid.grid.Cell;

public class Particle {

	public double x, y, u, v;

	public int i, j;

	private double a, b;
	private double s1, s2, s3, s4;

	public Particle(double x, double y, int i, int j) {
		this.x = x;
		this.y = y;
		this.i = i;
		this.j = j;
	}

	public void move(Cell[][] cells, double dx, double dy, double dt) {

		i = (int) (x / dx);
		j = (int) (y / dy);

		calculateAreas(dx, dy);

		u = calculateU(cells, dy);
		v = calculateV(cells, dx);

		x += u * dt;
		y += v * dt;
	}

	private double calculateV(Cell[][] cells, double dx) {

		double v1 = 0, v2 = 0, v3 = 0, v4 = 0;

		if (a != 0) {

			int ib = i - 1;

			if (a > 0.5 * dx) {
				++ib;
			}

			v1 = cells[ib][j].v;
			v2 = cells[ib + 1][j].v;
			v3 = cells[ib + 1][j - 1].v;
			v4 = cells[ib][j - 1].v;

		} else {

			v1 = (cells[i - 1][j].v + cells[i][j].v) / 2;
			v2 = (cells[i][j].v + cells[i + 1][j].v) / 2;
			v3 = (cells[i][j - 1].v + cells[i + 1][j - 1].v) / 2;
			v4 = (cells[i - 1][j - 1].v + cells[i][j - 1].v) / 2;

		}

		return s1 * v1 + s2 * v2 + s3 * v3 + s4 * v4;
	}

	private double calculateU(Cell[][] cells, double dy) {

		double u1 = 0, u2 = 0, u3 = 0, u4 = 0;

		if (b != 0.5) {

			int jb = j + 1;

			if (b < 0.5 * dy) {
				--jb;
			}

			if(i < 0 || jb < 0) {
				System.out.println("");
			}
			
			u1 = cells[i - 1][jb].u;
			u2 = cells[i][jb].u;
			u3 = cells[i][jb - 1].u;
			u4 = cells[i - 1][jb - 1].u;

		} else {

			u1 = (cells[i - 1][j + 1].u + cells[i - 1][j].u) / 2;
			u2 = (cells[i][j + 1].u + cells[i][j].u) / 2;
			u3 = (cells[i][j].u + cells[i][j - 1].u) / 2;
			u4 = (cells[i - 1][j].u + cells[i - 1][j - 1].u) / 2;

		}

		return s1 * u1 + s2 * u2 + s3 * u3 + s4 * u4;
	}

	private void calculateAreas(double dx, double dy) {
		a = x - (i - 0.5) * dx;
		b = y - (j - 0.5) * dy;

		s1 = a * (dy - b);
		s2 = (dx - a) * (dy - b);
		s3 = (dx - a) * b;
		s4 = a * b;
	}

}
